package cn.ilikes.tools.hbase.jpa.persistences;

import javax.persistence.EntityTransaction;
import javax.persistence.Query;

import org.slf4j.Logger;

import cn.ilikes.tools.hbase.jpa.JPAHbasePersistenUnitEnv;
import cn.ilikes.tools.hbase.jpa.clients.AbClient;
import cn.ilikes.tools.hbase.jpa.clients.Client;
import cn.ilikes.tools.hbase.jpa.metadatas.orms.elements.NamedQuery;
import cn.ilikes.tools.hbase.jpa.persistences.context.AbstractContext;
import cn.ilikes.tools.hbase.jpa.persistences.context.Operation;
import cn.ilikes.tools.hbase.jpa.persistences.context.operations.FindOperation;
import cn.ilikes.tools.hbase.jpa.persistences.context.operations.MergeOperation;
import cn.ilikes.tools.hbase.jpa.persistences.context.operations.PersistOperation;
import cn.ilikes.tools.hbase.jpa.query.HBaseQuery;
import cn.ilikes.tools.hbase.jpa.query.HbaseQueryImpl;
import cn.ilikes.tools.hbase.jpa.query.JPAHBaseQueryRunTimeException;
import cn.ilikes.tools.hbase.jpa.query.iquerys.JPAHBaseQuery;
import cn.ilikes.tools.hbase.jpa.query.iquerys.JPAQuery;
import cn.ilikes.tools.hbase.jpa.query.pasers.DefultIKunderaQueryParser;
import cn.ilikes.tools.hbase.jpa.query.pasers.IKunderaQueryParser;
import cn.ilikes.tools.hbase.jpa.query.pasers.JPQLParserException;
import cn.ilikes.tools.logs.Loggerfactory;

public class JPAHBaseEntityManager extends ABJPAHBaseEntityManager {

	public JPAHBaseEntityManager(JPAHbasePersistenUnitEnv hbasePersistenUnitEnv, AbClient clients) {
		super(hbasePersistenUnitEnv, clients);

	}

	private static Logger logger = Loggerfactory.instance(JPAHBaseEntityManager.class);

	@Override
	public EntityTransaction getTransaction() {
		AbstractContext abstractContext = getContext();
		EntityTransaction entityTransaction = abstractContext.createEntityTransaction();
		return entityTransaction;
	}

	@Override
	public <T> T find(Class<T> entityClass, Object key) {
		AbstractContext abstractContext = getContext();
		Operation<T> findOperation = new FindOperation<T>(PersistOperation.OperationType.find, abstractContext, entityClass, key);
		findOperation.init();
		@SuppressWarnings("unchecked")
		T value = (T) abstractContext.operation(findOperation);
		return value;

	}

	@Override
	public <T> T merge(T entity) {
		if (Loggerfactory.isdebug(logger))
			Loggerfactory.debug(logger, " persist : " + entity);
		AbstractContext abstractContext = getContext();
		Operation<T> persist = new MergeOperation<T>(PersistOperation.OperationType.saveorUpdate, abstractContext, entity);
		persist.init();
		abstractContext.operation(persist);
		return entity;
	}

	@Override
	public void persist(Object entity) {
		if (Loggerfactory.isdebug(logger))
			Loggerfactory.debug(logger, " persist : " + entity);
		AbstractContext abstractContext = getContext();
		Operation<Boolean> persist = new PersistOperation(PersistOperation.OperationType.insert, entity, abstractContext);
		persist.init();
		abstractContext.operation(persist);
	}

	@Override
	public void remove(Object arg0) {
		super.remove(arg0);
	}

	@Override
	public boolean contains(Object entity) {
		Object value = find(entity.getClass(), entity);
		if (value == null)
			return false;
		else
			return true;
	}

	@Override
	public void flush() {
		AbstractContext abstractContext = getContext();
		abstractContext.flush();
	}

	@Override
	public void close() {
		Loggerfactory.infoDebug(logger, "JPA  HBase  Entity  Manager close ；  ");
		AbstractContext abstractContext = getContext();
		abstractContext.clear();

	}

	@Override
	public Query createQuery(String arg0) {

		JPAQuery jpaQuery = new JPAHBaseQuery(arg0);
		try {
			IKunderaQueryParser kunderaQueryParser = new DefultIKunderaQueryParser(jpaQuery, arg0);
			kunderaQueryParser.parser();
		} catch (JPQLParserException e) {
			throw new JPAHBaseQueryRunTimeException(e);
		}

		HBaseQuery baseQuery = new HbaseQueryImpl(jpaQuery, getContext());
		return baseQuery;
	}

	@Override
	public Query createNamedQuery(String arg0) {
		AbstractContext abstractContext = getContext();
		NamedQuery namedQuery = abstractContext.getHbasePersistenUnitEnv().getOrmetaDataFactory().selectNamedQuery(arg0);
		if (namedQuery == null)
			throw new JPAHBaseQueryRunTimeException("not find name :  " + arg0 + " name query ! ");
		return createQuery(namedQuery.getQuery());
	}

}
